
#include <iostream>
#include <stdexcept>
#include "../Vector/ReferenceCounting2.h"

#define ASSERT_OK if(!this->ok()) { this->dump(); assert(!"ok() failed"); }

template <class Type>
class Stack : private Vector<Type>
{
    public:
        void push(Type elem);
        Type pop();
        Type top();
        Type last() const;
        bool empty() { return (size() == 0); }
        int size() const
        {
            //cout << "I want to return size!\n";

            return ((Vector<Type>)(*this)).size();
        }

        void dump() const;
        bool ok() const
        {
            return (this->size() >= 0);
        }
};

template <class Type>
void Stack<Type>::push(Type elem)
{
    //cout << "I am here\n";
    //cout << "Before push size is " << size();
    ASSERT_OK
    this->push_back(elem);
    ASSERT_OK
}

template <class Type>
Type Stack<Type>::last() const
{
    ASSERT_OK

    if(this->size() <= 0)
    {
        cout << "Stack is empty!";

        throw "Error to call stack::last() with empty stack!";
    }

    return (*this)[this->size() - 1];
    ASSERT_OK
}

template <class Type>
Type Stack<Type>::pop()
{
    ASSERT_OK

    Type last = this->last();

    if(this->size() <= 0) throw "You cant pop anything because there aren't any elements in stack!";

    this->pop_back();
    return last;
    ASSERT_OK
}

template <class Type>
void Stack<Type>::dump() const
{
    cout << "Hello, I'm stack dump, but I was created from vector by inheritance\n"
         << "So I'm going to call Vector::dump()\n\n";

    Vector<Type> this_vector = (Vector<Type>)(*this);

    this_vector.dump();

    cout << "\nIt's dump of Stack again. Last is: " << last();
}
